//---------------------------------------------------------------------
// File: ReceivePortConductorExStep.cs
// 
// Summary: Revision of the basic receive port conductor step to use the Object model
//
// Copyright (c) Hammersmith & Fulham Bridge Partnership. All rights reserved.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//---------------------------------------------------------------------

using System;
using System.Threading;
using System.Xml;
using Microsoft.BizTalk.ExplorerOM;
using Microsoft.Services.BizTalkApplicationFramework.BizUnit;

namespace BizUnit.Extensions.BizTalk
{
	/// <summary>
	/// The ReceivePortConductorExStep enables or disables a receive location.
	/// This step replaces the out of the box step with code that uses the OM 
	/// </summary>
	/// <remarks>
	/// The following shows an example of the Xml representation of this test step.
	/// 
	/// <code escaped="true">
	/// <TestStep assemblyPath="BizUnitExtensions.BizTalk.dll" typeName="BizUnit.Extensions.BizTalk.ReceivePortConductorExStep">
	///		<DelayForCompletion>5</DelayForCompletion> <!-- Optional, seconds to delay for this step to complete -->
	///		<ReceivePortName></ReceivePortName>
	///		<ReceiveLocationName></ReceiveLocationName>
	///		<Action>Enable</Action>
	/// </TestStep>
	/// </code>
	///	
	///	<list type="table">
	///		<listheader>
	///			<term>Tag</term>
	///			<description>Description</description>
	///		</listheader>
	///		<item>
	///			<term>DelayForCompletion</term>
	///			<description>The number of seconds to deplay for this step to complete</description>
	///		</item>
	///		<item>
	///			<term>ReceivePortName</term>
	///			<description>The name of the receive port to containing the receive location to enable/dissable</description>
	///		</item>
	///		<item>
	///			<term>ReceiveLocationName</term>
	///			<description>The name of the receive location to enable/dissable</description>
	///		</item>
	///		<item>
	///			<term>Action</term>
	///			<description>Enable|Disable</description>
	///		</item>
	///	</list>
	///	</remarks>

	public class ReceivePortConductorExStep : ITestStep
	{
		/// <summary>
		/// enumeration to control the action applied to the receive port
		/// </summary>
		public enum ReceivePortAction 
		{
			/// <summary>
			/// enables the receive port
			/// </summary>
			Enable,
			/// <summary>
			/// disables the receive port
			/// </summary>
			Disable,
		}

		#region ITestStep Members

		/// <summary>
		/// ITestStep.Execute() implementation
		/// </summary>
		/// <param name='testConfig'>The Xml fragment containing the configuration for this test step</param>
		/// <param name='context'>The context for the test, this holds state that is passed beteen tests</param>
		public void Execute(XmlNode testConfig, Context context)
		{
			string receivePortName;
			string receiveLocationName;
			string connectionString;

			try
			{
				receivePortName = context.ReadConfigAsString(testConfig, "ReceivePortName");
				receiveLocationName = context.ReadConfigAsString(testConfig, "ReceiveLocationName");
				connectionString = context.ReadConfigAsString(testConfig, "ConnectionString");
			}
			catch (Exception e)
			{
				context.LogInfo("There was an error while setting the parameters for this operation. Check that your test step includes arguments includes arguments for AssemblyName, OrchestrationName, and ConnectionString.");
				throw e;
			}

			ReceivePortAction action = (ReceivePortAction)Enum.Parse( typeof(ReceivePortAction), context.ReadConfigAsString(testConfig, "Action"), true );

			ControlLocation(receivePortName, receiveLocationName, connectionString, action, context );

			// Delay if necessary to allow the orchestration to start/stop
			int delayForCompletion = context.ReadConfigAsInt32(testConfig, "DelayForCompletion", true);
			if (delayForCompletion > 0)
			{
				context.LogInfo("Waiting for {0} seconds before recommencing testing.", delayForCompletion);
				Thread.Sleep(delayForCompletion*1000);
			}
		}

		#endregion

		private void ControlLocation( string receivePortName, string receiveLocationName, string connectionString, ReceivePortAction action, Context context )
		{

			string[] userMessage = new string[2];
			#region Set feedback text
			if (action == ReceivePortAction.Enable)
			{
				userMessage[0] = "started";
				userMessage[1] = "starting";
			}
			else
			{
				userMessage[0] = "stopped";
				userMessage[1] = "stopping";
			}
			#endregion

			BtsCatalogExplorer root = new BtsCatalogExplorer();
			try
			{
				root.ConnectionString = connectionString;
				ReceivePort recvPort = root.ReceivePorts[receivePortName];
				ReceiveLocation recvLocation = recvPort.ReceiveLocations[receiveLocationName];
				if(action == ReceivePortAction.Enable)
					recvLocation.Enable = true;
				else
					recvLocation.Enable = false;

				//Try to commit the changes made so far. If it fails, roll-back 
				//all the changes.
				root.SaveChanges();
				context.LogInfo(String.Format("Receive Location {0} for port {1} has been {2}.", receiveLocationName, receivePortName, userMessage[0]));

			}
			catch(Exception e)
			{
				root.DiscardChanges();
				context.LogInfo(String.Format("There was an error {0} receive Location {1} for port {2}.", userMessage[1], receiveLocationName, receivePortName));
				context.LogException(e);
			}
		}

		
	}
}
